#include <iostream>
#include <cstring> // for strcpy
#include <vector>
#include <exception>

using namespace std;
//===============================const 修饰普通变量=================================================================
//当考虑const修饰的是谁的时候，把数据类型删掉，就近原则即可

// int main(){
//     const int a = 10;//变量a是只读的
//     //a = 20; // 这行代码会导致编译错误，因为a是常量

//     int x = 100;
//     const int *p = &x; // p是指向x的指针 const修饰表示*p是只读的，指向的内存空间中的内容不可修改
//     //*p = 10; // 这行代码会导致编译错误，因为*p是只读的

//     int const *q = &x; // q是指向x的指针 const修饰表示*q是只读的，指向的内存空间中的内容不可修改 和上面的语句相同效果

//     int *const r1 = &x; // r1是指向x的常量指针，指针本身不可修改，但可以修改指针所指向的内容
//     *r1 = 200; // 这行代码是合法的，因为r1指向的内容可以修改

//     const int *const r = &x; // r是指向x的常量指针，既不能修改指针本身，也不能修改指针所指向的内容
    
//     int const *const m = &x; // m是指向x的常量指针，既不能修改指针本身，也不能修改指针所指向的内容
    
//     return 0;
// }

//=================================const 修饰成员变量=======================================================================
// class A{
//     public:
//         const int a;//成员常量，只能在初始化成员列表中被赋值

//         A():a(100){}
//         /*A a1;
//           a1.a = 1000;//错的 
//         */
// };

//=======================================const 修饰类的成员函数===============================================
// class B{
//     public:
//         int x;
//         B(): x(10) {}

//         int getX() const{
//             x++; // 这行代码会导致编译错误，因为getX是一个const成员函数，不能修改成员变量x
//             return x;
//         }
// };
// int main(){
//     B b;
//     cout << b.getX() << endl; // 这行代码会导致编译错误，因为getX是一个const成员函数，不能修改成员变量x
//     return 0;
// }

//=======================================const 修饰对象==================================================================
// class C{
//     public:
//         int x;
//         C():x(10){}

//         int getX() const {
//             return x; // 这行代码是合法的，因为getX是一个const成员函数，不能修改成员变量x
//         }
// };

// int main(){
//     const C c;
//     //c.x = 20; // 这行代码会导致编译错误，因为c是一个const对象，不能修改其成员变量x
//     cout << c.x << endl; // 合法，可以访问public成员变量，但是不能修改
//     c.getX(); // 这行代码是合法的，因为getX是一个const成员函数，可以被const对象调用
//     cout << c.getX() << endl; // 这行代码是合法的，因为getX是一个const成员函数，可以被const对象调用
//     return 0;
// }

//================================================const 修饰函数返回值=============================================================
// const int getValue(){
//     int x = 10;
//     return x; // 返回值是一个临时对象，const修饰表示返回的值是只读的
// }

// int main(){
//     const int value = getValue(); // value是一个只读的变量
//     //value = 20; // 这行代码会导致编译错误，因为value是const的，不能修改

//     cout << "The value is: " << value << endl; // 输出: The value is: 10

//     return 0;
// }

// class B{
//     public:
//         int x;
//         B():x(100){

//         }

//         int getX() const {
//             return x; // 这行代码是合法的，因为getX是一个const成员函数，不能修改成员变量x
//         }
// };

// const B getB(){
//     B b;
//     return b; // 返回一个B对象，const修饰表示返回的对象是只读的
// }

// int main(){
//     B b = getB();
//     cout << b.x << endl;
//     return 0;
// }
//const修饰函数返回值为普通的常量或者对象时如上，加不加const修饰是一样的；
//但如果函数的返回值是指针或引用时，加上const修饰可以防止通过返回值修改原对象，如下

// class B{
//     public:
//         int x;
//         B():x(100){

//         }

//         int getX() const {
//             return x; // 这行代码是合法的，因为getX是一个const成员函数，不能修改成员变量x
//         }
// };

// const char *func(){
//     char *str = new char [10];
//     strcpy(str, "hello");
//     return str;
//}//返回一个指向字符串的指针，在内存中也会有一个临时空间用于保存这个返回值

// const B &func1(){//等价于返回值是const B *func1()
//     B b;
//     return b; // 返回一个B对象的引用，const修饰表示返回的对象是只读的
//     // 注意：这里返回的是局部变量b的引用，可能会导致未定义行为，因为b在函数结束后会被销毁
//     //编译器在处理时return &b，返回的是栈上的一个地址 是有问题的
// }

// const B &func2(const B &t){
//     return t; // 返回一个B对象的引用，const修饰表示返回的对象是只读的

// }

// int main(){
//     // const char *p = func(); // p是一个指向字符串的常量指针，不能通过p修改字符串内容
//     // cout << p << endl;

//     //char *q = func(); // 这行代码会导致编译错误，因为func返回的是一个const char*，不能赋值给char*
//     B b;
//     B t = func2(b);// t是一个B对象的副本，func2返回的是b的引用
//     const B &r = func2(b); // r是一个指向B对象的常量引用，不能通过r修改B对象的内容
//     return 0;
// }

//==================================================extern "C"==================================================

// extern "C"{
//     //extern int add(int x, int y);
//     #include"example.h"
// }
// #include "example.h"

// int main(){
//     add(2, 3);
//     return 0;
// }

//=====================================================nullptr===========================================================
// void func(int *p){
//     cout << "func1 called with int pointer" << endl;
// }

// void func(int p){
//     cout << "func2 called with int value" << endl;
// }

// int main(){
//     int *p = NULL;//C中，NULL == (void*) 0   C++中，NULL == 0

//     func(nullptr);

//     int *p1 = NULL;
//     func(p1); // 调用func(int *p)

//     return 0;
// }

//=============================================================异常===========================================================
int func(int a, int b){
    if(b)
        return a / b; // 如果b为0，将抛出异常
    else//如果这里返回的是普通的调试语句比如printf或者cout，我们只知道运行到这儿了但不知道是什么问题
    {
        cout << "division 0" << endl;
        throw "除数不能为0"; // 抛出一个异常
    }
}

int main(){
    try{
        vector<int> arr(3,10); // 创建一个大小为3，初始值为10的vector
        for(int i = 0; i < 3; i++) {
            cout << arr.at(i) << endl; // 输出: 10 10 10
        }

        arr.at(3) = 100; // 这行代码会导致运行时错误，因为索引3超出了vector的范围
    }
    catch(out_of_range &e){
        cout << "发生异常" << endl; // 捕获所有异常并输出错误信息
        cout << e.what() << endl; // 输出异常信息
    }

    try{
        int ret = func(10 , 0); // 这行代码会导致运行时错误，因为除数为0
        cout <<"end....." << endl; // 这行代码不会被执行，因为func抛出了异常
    }
    catch(...){
        cout << "err" << endl; // 捕获所有异常并输出错误信息
    }
    return 0;
}